﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Xml;
//using System.Xml.Serialization;
namespace CardsServer.WCF
{
    public class VirtualServer
    {
        private Server m_pOwnerServer = null;
        private Guid m_ID;
        private string m_Name = "";
        private DateTime m_StartTime;
        private Type m_Type = null;
        private Type m_IType = null;
        private string m_Address = "";
        private bool m_Running = false;
        private ServiceHost host = null;
        private string ServerCertificateName = "";
        private string ServerCertificatePass = "";
        private string m_BindingType = "";
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="server">Server what owns this virtual server.</param>
        /// <param name="id">Virtual server ID.</param>
        /// <param name="name">Virtual server name.</param>
        /// <param name="apiInitString">Virtual server api initi string.</param>
        /// <param name="api">Virtual server API.</param>
        public VirtualServer(Server server, Guid id, string name, Type svcType, Type itype, string address,string bindingtype)
        {
            m_pOwnerServer = server;
            m_ID = id;
            m_Name = name;
            m_Type = svcType;
            m_IType = itype;
            m_Address = address;
            m_BindingType = bindingtype;
        }

        #region method Start

        /// <summary>
        /// Starts this virtual server.
        /// </summary>
        public void Start()
        {
            if (m_Running)
            {
                return;
            }
            Uri tcpa = new Uri(m_Address);
            string strtcpc = m_Address.Substring(0, m_Address.LastIndexOf("/"));
            string port = strtcpc.Substring(strtcpc.LastIndexOf(":") + 1, strtcpc.Length - strtcpc.LastIndexOf(":") - 1);
            strtcpc = strtcpc.Substring(0, strtcpc.LastIndexOf(":"));
            port = ":" + (int.Parse(port) + 1).ToString() + "/" + m_Type.Name.ToString();
            strtcpc = strtcpc + port;
            //myLog.WriteEntry(strtcpc, EventLogEntryType.Information);
            Uri tcpc = new Uri(strtcpc);

            XmlDictionaryReaderQuotas quotas = new XmlDictionaryReaderQuotas();
            quotas.MaxDepth = 64;
            quotas.MaxStringContentLength = 2147483647;
            quotas.MaxArrayLength = 2147483647;
            quotas.MaxNameTableCharCount = 2147483647;

            switch (m_BindingType)
            {
                case "NetTcpBinding":


            //Uri bpa = new Uri("net.pipe://localhost/NetNamedPipeBinding");
            //Uri tcpa = new Uri("net.tcp://localhost:8005/TcpBinding");

            //host = new ServiceHost(typeof(ServiceClass), bpa, tcpa);
            host = new ServiceHost(m_Type, tcpa);

            //NetNamedPipeBinding pb = new NetNamedPipeBinding();
            NetTcpBinding tcpb = new NetTcpBinding();
            tcpb.CloseTimeout = new TimeSpan(10, 10, 10); 
            tcpb.OpenTimeout = new TimeSpan(10, 10, 10); 
            tcpb.ReceiveTimeout = new TimeSpan(10, 10, 10);
 
            tcpb.MaxReceivedMessageSize = 2147483647;
            tcpb.MaxBufferPoolSize = 2147483647;
            tcpb.MaxBufferSize = 2147483647;
            //ServiceCredentials sc = new ServiceCredentials();
            //        sc.ServiceCertificate.Certificate.
            //tcpb.PortSharingEnabled = true;
            tcpb.TransferMode = TransferMode.Streamed;
            tcpb.SendTimeout = new TimeSpan(10, 10, 10);
            tcpb.ReaderQuotas = quotas;
            tcpb.TransactionFlow = true;
                    tcpb.Security.Mode=SecurityMode.None;
            ServiceMetadataBehavior mBehave = new ServiceMetadataBehavior();
            mBehave.HttpsGetEnabled = false;
            host.Description.Behaviors.Add(mBehave);
            host.AddServiceEndpoint(typeof(IMetadataExchange), 
                
                MetadataExchangeBindings.CreateMexTcpBinding(), "mex");

            //host.AddServiceEndpoint(typeof(IMetadataExchange), 
            //    MetadataExchangeBindings.CreateMexNamedPipeBinding(), "mex");

            //host.AddServiceEndpoint(m_Type, pb, bpa);
            host.AddServiceEndpoint(m_IType, tcpb, tcpa);
                    break;
                case "BasicHttpBinding":
                    System.ServiceModel.BasicHttpBinding bh = new BasicHttpBinding();
                    ServerCertificateName = Tools.MyConfig.getAppValue("ServerCertificateName");
                    ServerCertificatePass = Tools.MyConfig.getAppValue("ServerCertificatePass");
                    //计算不同端口

                    host = new ServiceHost(m_Type, tcpa);
                    ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
                    behavior.HttpGetEnabled = true;

                    host.Description.Behaviors.Add(behavior);

                    bh.ReaderQuotas = quotas;
                    bh.MaxReceivedMessageSize = 2147483647;
                    Type y = host.GetType();
                    object obj = y.Assembly.CreateInstance("System.ServiceModel.Dispatcher.DataContractSerializerServiceBehavior", true, BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { false, Int32.MaxValue }, null, null);
                    IServiceBehavior myServiceBehavior = obj as IServiceBehavior;
                    if (myServiceBehavior != null)
                    {
                        host.Description.Behaviors.Add(myServiceBehavior);
                    }

                    //用于与客户端通信

                    host.AddServiceEndpoint(m_IType, bh, tcpc);

                    break;

            }

            //打开服务  
            try
            {
                host.Open();
                m_StartTime = DateTime.Now;
                m_Running = true;
            }
            catch (Exception ex)
            {

                Error.DumpError(ex);
            }


        }
        #endregion

        #region method Stop

        /// <summary>
        /// Stops this virtual server.
        /// </summary>
        public void Stop()
        {
            try
            {
                host.Close();

                m_Running = false;
            }
            catch (Exception ex)
            {
                //myLog.WriteEntry(ex.Message, EventLogEntryType.Error);

            }

        }

        #endregion

        #region method OnError

        /// <summary>
        /// Is called when error happens.
        /// </summary>
        /// <param name="x"></param>
        private void OnError(Exception x)
        {
            Error.DumpError(this.Name, x);
        }

        #endregion

        /// <summary>
        /// Starts or stops server.
        /// </summary>
        public bool Enabled
        {
            get { return m_Running; }

            set
            {
                if (value)
                {
                    Start();
                }
                else
                {
                    Stop();
                }
            }
        }

        /// <summary>
        /// Gets virtual server ID.
        /// </summary>
        public Guid ID
        {
            get { return m_ID; }
        }

        /// <summary>
        /// Gets virtual server name
        /// </summary>
        public string Name
        {
            get { return m_Name; }
        }

        public Type SVRType
        {
            get { return m_Type; }
        }

        public Type SVRIType
        {
            get { return m_IType; }
        }

        public string Address
        {
            get { return m_Address; }
        }

        public DateTime StartDate
        {
            get { return m_StartTime; }
        }
    }
}
